package com.zhuangyuan.cloud.data.service;

import com.zhuangyuan.cloud.data.entities.BaseEntity;
import com.zhuangyuan.cloud.data.entities.Cate;
import com.zhuangyuan.cloud.data.entities.CateCategory;
import com.zhuangyuan.cloud.data.entities.FileRecycleBin;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.PropertyAccessor;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.*;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public abstract class ABaseService implements BaseService {

    @Autowired
    private EntityManagerFactory entityManagerFactory;

    @Override
    public <T extends BaseEntity> boolean exists(Class<T> clazz, Map<String, Object> propValue) throws Exception {
        T obj = null;
        try {
            obj = clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new Exception(e.getMessage());
        }
        PropertyAccessor accessor = PropertyAccessorFactory.forBeanPropertyAccess(obj);

        Iterator<String> iterator = propValue.keySet().iterator();

        String hql = String.format("select count(h) from %s h where ",clazz.getSimpleName());
        int index = 0;
        while (iterator.hasNext()){
            String prop = iterator.next();
            if(index > 0)
                hql += " and ";
            hql = hql + String.format(" h.%s = :%s",prop,prop);
            index++;
        }
        Session session = entityManagerFactory.unwrap(SessionFactory.class).openSession();
        Query query = session.createQuery(hql);
        iterator = propValue.keySet().iterator();
        while (iterator.hasNext()){
            String prop = iterator.next();
            query.setParameter(prop,propValue.get(prop));
        }

        long count = (long) query.getSingleResult();
        return count > 0;
    }

    protected abstract  JpaRepository getRepository();

    @Override
    public <T extends BaseEntity> T save(T entity) {
        return (T) getRepository().save(entity);
    }

    @Override
    public <T extends BaseEntity> T get(String id) {
        Optional<T> opt = getRepository().findById(id);
        if(opt.isPresent())
            return opt.get();
        else return null;
    }

    @Override
    public <T extends BaseEntity> List<T> list() {
        return getRepository().findAll();
    }

    @Override
    public <T extends BaseEntity> boolean delete(T obj) {
        getRepository().delete(obj);
        return true;
    }

    @Override
    public <T extends BaseEntity> T update(T obj) {
        getRepository().save(obj);
        return obj;
    }

    public void testJpaCriteria(){
        String cateId = "65064b65-1609-4f2b-af03-e9877fe58386";
        EntityManagerFactory factory = entityManagerFactory;
        EntityManager manager = factory.createEntityManager();
        CriteriaBuilder builder = factory.getCriteriaBuilder();
        CriteriaQuery<CateCategory> query = builder.createQuery(CateCategory.class);
        Root<CateCategory> from = query.from(CateCategory.class);
//        Join<CateCategory, Cate> ccJoin = from.join("cate");
        Join<Object, Object> ccJoin = from.join("cate", JoinType.INNER).on(builder.equal(from.get("cate").get("id"),cateId));

        query.where(builder.equal(from.get("cate").get("id"),cateId));
        TypedQuery<CateCategory> typedQuery = manager.createQuery(query);
        List<CateCategory> list =  typedQuery.getResultList();

        System.out.println(list);
    }
}
